<template>
  <root-portal v-if="visibleAsync">
    <uni-popup
      ref="popup"
      :type="type"
      mask-background-color="rgba(255,255,255,0.8)"
      @change="popupChange"
    >
      <view class="dialog">
        <view
          v-if="title"
          class="dialog-header"
        >
          {{ title }}
        </view>
        <view class="dialog-body">
          <slot></slot>
        </view>
        <view
          v-if="showClose"
          class="dialog-footer"
        >
          <view
            class="dialog-footer-btn"
            :class="{ big: closeText }"
            @click="close"
          >
            <text v-if="closeText">{{ closeText }}</text>
            <text
              v-else
              class="iconfont icon-close-bold"
            ></text>
          </view>
        </view>
      </view> </uni-popup
  ></root-portal>
</template>

<script>
  export default {
    props: {
      type: {
        type: String,
        default: "center",
      },
      visible: {
        type: Boolean,
        default: false,
      },

      title: {
        type: String,
        default: "",
      },

      showClose: {
        type: Boolean,
        default: true,
      },
      closeText: {
        type: String,
        default: "",
      },
    },
    data() {
      return {
        visibleAsync: false,
      };
    },
    watch: {
      visible(newValue) {
        this.visibleAsync = newValue;
        if (newValue) {
          this.$nextTick(() => {
            this.$refs.popup.open();
            this.$emit("open");
          });
        } else {
          this.$nextTick(() => {
            this.$emit("close");
          });
        }
      },
    },
    mounted() {
      this.visibleAsync = this.visible;
      if (this.visible) {
        this.$nextTick(() => {
          this.$refs.popup.open();
          this.$emit("open");
        });
      }

      uni.addInterceptor("navigateBack", {
        invoke: (res) => {
          this.close();

          return res;
        },
      });

      uni.addInterceptor("navigateTo", {
        invoke: (res) => {
          this.close();

          return res;
        },
      });

      uni.addInterceptor("redirectTo", {
        invoke: (res) => {
          this.close();

          return res;
        },
      });

      uni.addInterceptor("switchTab", {
        invoke: (res) => {
          this.close();

          return res;
        },
      });

      uni.addInterceptor("reLaunch", {
        invoke: (res) => {
          this.close();

          return res;
        },
      });
    },
    methods: {
      popupChange(e) {
        this.$emit("change", e.show);
        this.$emit("update:visible", e.show);
        if (e.show) {
          this.$emit("open");
        } else {
          this.$emit("close");
        }
      },

      close() {
        if (this.visibleAsync) {
          this.$refs.popup.close();
          this.visibleAsync = false;
        }
        this.$nextTick(() => {
          this.$emit("close");
          this.$emit("update:visible", false);
        });
      },
    },
  };
</script>

<style lang="scss" scoped>
  $width: calc(100vw - #{$margin * 2});
  $height: 320rpx;
  .dialog {
    display: flex;
    flex-direction: column;

    width: $width;
    min-height: $height;
    max-height: calc(100vh - 240rpx);
    max-height: calc(100vh - 240rpx - constant(safe-area-inset-bottom));
    max-height: calc(100vh - 240rpx - env(safe-area-inset-bottom));

    background: rgba(255, 255, 255, 0.5);
    background-clip: padding-box;
    backdrop-filter: blur(20rpx);

    border: solid 2rpx #fff;
    border-radius: $border-radius;

    box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.3);

    &-header {
      padding: $padding;
      padding-bottom: 0;

      font-size: 28rpx;
      font-weight: bold;

      text-align: center;

      color: rgba($color: $color-primary, $alpha: 0.8);
    }
    &-body {
      flex: 1;
      display: flex;
      flex-direction: column;

      overflow: auto;

      padding: $padding;
    }
    &-footer {
      display: flex;
      justify-content: center;

      padding: $padding;

      &-btn {
        display: flex;
        justify-content: center;
        align-items: center;

        width: 40rpx;
        height: 40rpx;

        background: rgba($color: $color-primary, $alpha: 0.8);

        font-size: 24rpx;
        color: $color-white;

        border-radius: 50%;
        box-shadow: $box-shadow;

        &.big {
          width: unset;
          height: 40rpx;
          padding-left: 20rpx;
          padding-right: 20rpx;
          border-radius: 20rpx;
        }
      }
    }
  }
</style>
